<template>
  <el-scrollbar height="100vh">
    <div class="container">
      <el-affix :offset="1">
        <h1 class="title">标记点 marker，鼠标移动到点展示信息</h1>
      </el-affix>
      <div id="map" class="map-x" ref="mapBox"></div>
      <el-row class="mb-4" style="margin-top: 20px;">
        <el-button type="success" round @click="rotateRight()"><el-icon><refresh-left /></el-icon></el-button>
        <el-button type="success" round @click="rotateLeft()"><el-icon><refresh-right /></el-icon></el-button>
        <el-button type="success" round @click="panToQH()">平移到青海</el-button>
        <el-button type="success" round @click="elasticToHN()">弹性平移到海南</el-button>
        <el-button type="success" round @click="bounceToHEB()">弹跳平移到哈尔滨</el-button>
        <el-button type="success" round @click="spinToQD()">旋转平移到青岛</el-button>
        <el-button type="success" round @click="rotateAroundBJ()">绕着北京旋转</el-button>
        <el-button type="success" round @click="flyToWLMQ()">飞行到乌鲁木齐</el-button>
      </el-row>
      <div class="codestyle"><Code /></div>
      <dl>
        <dt>easing属性：</dt>
        <dd>easeIn: 开始缓慢并加快速度。</dd>
        <dd>easeOut: 快速开始和减速。</dd>
        <dd>inAndOut: 开始慢，加速，然后再减速。</dd>
        <dd>linear: 随着时间的推移保持恒定的速度。</dd>
        <dd>easeIn: 开始缓慢并加快速度。</dd>
      </dl>
    </div>
  </el-scrollbar>
</template>
<script>
import { onMounted, reactive, ref, toRefs } from 'vue-demi'
import 'ol/ol.css'
import { Map, View } from 'ol'
import Tile from 'ol/layer/Tile'
import XYZ from 'ol/source/XYZ'
import * as olEasing from 'ol/easing'
import mapUtils from '../../utils/animate.js'
import Code from './code.vue'
export default {
  setup () {
    const state = reactive({
      map: ref(null),
      mapBox: ref(null),
      QH: [102.408056, 36.477499],
      HN: [109.912898, 19.444487],
      HEB: [126.553827, 45.840007],
      QD: [120.390733, 36.123837],
      BJ: [116.380122, 39.991705],
      WLMQ: [87.60675, 43.850841]
    })

    const init = () => {
      state.map = new Map({
        target: state.mapBox,
        layers: [
          new Tile({
            source: new XYZ({
              url: 'http://map.geoq.cn/ArcGIS/rest/services/ChinaOnlineStreetPurplishBlue/MapServer/tile/{z}/{y}/{x}'
            })
          })
        ],
        view: new View({
          // 地图视图
          projection: 'EPSG:4326', // 坐标系，有EPSG:4326和EPSG:3857
          center: [116.41400, 39.91500], // 北京坐标
          zoom: 7 // 地图缩放级别（打开页面时默认级别）
        })
      })
    }

    // 点击左旋转
    const rotateLeft = () => {
      const rotate = state.map.getView().getRotation()
      state.map.getView().animate({
        rotation: rotate + 1
      })
    }

    // 点击右旋转
    const rotateRight = () => {
      const rotate = state.map.getView().getRotation()
      state.map.getView().animate({
        rotation: rotate - 1
      })
    }

    // 平移到青海
    const panToQH = () => { // 平移到伦敦
      state.map.getView().animate({
        center: state.QH, // 目标位置
        duration: 2000 // 动画时长
      })
    }

    // 弹性平移到海南
    const elasticToHN = () => { // 弹性平移到莫斯科
      state.map.getView().animate({
        center: state.HN, // 目标位置
        easing: olEasing.easeOut, // 动画: 传入动画函数，olEasing是内置动画集
        duration: 2000 // 动画时长
      })
    }

    // 弹跳平移到呼伦贝尔
    const bounceToHEB = () => {
      state.map.getView().animate({
        center: state.HEB,
        duration: 2000, // 动画时长
        easing: mapUtils.bounce // 动画：传入动画函数
      })
    }

    // 旋转平移到青岛
    const spinToQD = () => {
      const view = state.map.getView()
      const center = view.getCenter()

      view.animate({
        center: [
          center[0] + (state.QD[0] - center[0]) / 2,
          center[1] + (state.QD[1] - center[1]) / 2
        ],
        rotation: Math.PI,
        easing: olEasing.easeOut // 动画: 传入动画函数，olEasing是内置动画集
      }, {
        center: state.QD,
        rotation: 2 * Math.PI, // 旋转角度
        easing: olEasing.easeOut
      })
    }

    //
    const rotateAroundBJ = () => {
      const view = state.map.getView()
      const rotation = view.getRotation()
      view.animate({ // 将多个动画连在一起使用
        rotation: rotation + Math.PI,
        anchor: state.BJ, // 锚点
        easing: olEasing.easeIn // 动画：传入动画函数
      }, {
        rotation: rotation + 2 * Math.PI,
        anchor: state.BJ, // 锚点
        easing: olEasing.easeOut // 动画：传入动画函数
      })
    }

    const flyToWLMQ = () => {
      flyTo(state.WLMQ)
    }

    // 飞行到乌鲁木齐
    // eslint-disable-next-line @typescript-eslint/no-empty-function
    const flyTo = (location, done = async () => {}) => {
      const view = state.map.getView()
      const duration = 2000
      const zoom = view.getZoom()
      let parts = 2
      let called = false
      function callback (complete) {
        --parts
        if (called) {
          return
        }
        if (parts === 0 || !complete) {
          called = true
          done(complete)
        }
      }
      view.animate({
        center: location,
        duration: duration
      }, callback)
      view.animate({
        zoom: zoom - 1,
        duration: duration / 2
      }, {
        zoom: zoom,
        duration: duration / 2
      }, callback)
    }

    onMounted(() => {
      init()
    })
    return {
      ...toRefs(state),
      rotateLeft,
      rotateRight,
      panToQH,
      elasticToHN,
      spinToQD,
      bounceToHEB,
      rotateAroundBJ,
      flyToWLMQ
    }
  },
  components: {
    Code
  }
}
</script>
<style lang="scss" scoped>
@import '../../css/main.scss';
</style>
